package xcmg.device.web.warehouse;

import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import xcmg.device.infra.BasicController;
import xcmg.device.infra.ErrorCode;
import xcmg.device.service.company.CompanyInfoService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.warehouse.*;
import xcmg.device.service.warehouse.WarehouseDeliveryRecordService;
import xcmg.device.util.RedisConstant;
import yb.ecp.fast.infra.annotation.FastMappingInfo;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ListUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/warehouseDeliveryRecord")
public class WarehouseDeliveryRecordController extends BasicController {
    @Autowired
    private WarehouseDeliveryRecordService warehouseDeliveryRecordService;
    @Autowired
    private CompanyInfoService companyInfoService;
    @Autowired
    private RedissonClient redissonClient;

    @RequestMapping(value = "/add",method = RequestMethod.POST)
    @ApiOperation(value = "增加出库记录")
    @FastMappingInfo(needLogin = true)
    public ActionResult warehouse(@RequestBody WarehouseDeliveryRecordBatchAddVO warehouseDeliveryRecordBatchAddVO)throws Exception{
        if(null == warehouseDeliveryRecordBatchAddVO || ListUtil.isNullOrEmpty(warehouseDeliveryRecordBatchAddVO.getRecordList())){
            return actionResult(ErrorCode.IllegalArument);
        }
        WarehouseDeliveryRecordAddVO deliveryRecord = warehouseDeliveryRecordBatchAddVO.getRecordList().get(0);
        String barCode = deliveryRecord.getBarCode();
        if(StringUtils.isEmpty(barCode)){
            return actionResult(ErrorCode.IllegalArument);
        }
        String sysSapMaterialsInfoCacheKey = RedisConstant.RedisKeyContant.PDA_OUTBOUND_BARCODE_CACHE_KEY+barCode;
        RLock lock = redissonClient.getLock(sysSapMaterialsInfoCacheKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(0,RedisConstant.OUT_INBOUND_LOCK_TIME, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("pda扫码出库获取分布式锁异常{}",e);
            return actionResult(ErrorCode.PdaOutboundLockError);
        }
        if(!isLock){
            log.warn("pda扫码出库存在已经执行的任务,无法获取锁，本次不执行");
            return actionResult(ErrorCode.PdaOutboundLockError);
        }
        FunctionResult result = new FunctionResult();
        List<WarehouseDeliveryRecordAddVO> errorList = new ArrayList<>();
        try{
            String orgId = getOrgId();
//            CompanyInfoDO companyInfo = companyInfoService.getByOrgId(orgId);
//            String sapCode = companyInfo.getSapCode();
//            boolean isZx = CompanyUtil.isZXSapCode(sapCode);
//            if(isZx){
//                return actionResult(ErrorCode.ZxRequestNotSupport);
//            }
            ErrorCode errorCode = warehouseDeliveryRecordService.batchAdd(warehouseDeliveryRecordBatchAddVO, getUserId(), orgId);
            if (errorCode == ErrorCode.Success) {
                return actionValueResult(warehouseDeliveryRecordBatchAddVO.getBarcodeManageVOS());
            }
            result.setCode(errorCode);
        }catch (Exception e){
            LogHelper.error("/warehouseDeliveryRecord/add   异常|"+e.getMessage(),ErrorCode.Failure.getCode());
            WarehouseDeliveryRecordAddVO recordAddVO = warehouseDeliveryRecordBatchAddVO.getRecordList().get(getIndex(e.getMessage()));
            recordAddVO.setRemark(getMsg(e.getMessage()));
            errorList.add(recordAddVO);
            for(int i=0;i<warehouseDeliveryRecordBatchAddVO.getRecordList().size();i++){
                if(i != getIndex(e.getMessage())){
                    errorList.add(warehouseDeliveryRecordBatchAddVO.getRecordList().get(i));
                }
            }
            result.setCode(ErrorCode.Failure);
            result.setValue(errorList);
            LogHelper.monitor(getExceptionAllinformation(e));
        }finally {
            lock.unlock();
        }

        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/receive",method = RequestMethod.POST)
    @ApiOperation(value = "无条码化出库")
    @FastMappingInfo(needLogin = true)
    public ActionResult receive(@RequestBody WarehouseDeliveryAddVO deliveryAddVO)throws Exception{
        if(null == deliveryAddVO || ListUtil.isNullOrEmpty(deliveryAddVO.getDetailList())){
            return actionResult(ErrorCode.IllegalArument);
        }
        String businessOrder = deliveryAddVO.getHeaderInfo().getBusinessOrder();
        String noBarcodeOutboundBusinessOrderCacheKey = RedisConstant.RedisKeyContant.NOBARCODE_OUTBOUND_BUSINESSORDER_CACHE_KEY+businessOrder;
        RLock lock = redissonClient.getLock(noBarcodeOutboundBusinessOrderCacheKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(0,RedisConstant.OUT_INBOUND_LOCK_TIME, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("非条码出库获取分布式锁异常{}",e);
            return actionResult(ErrorCode.NoBarcodeOutboundLockError);
        }
        if(!isLock){
            log.warn("非条码出库存在已经执行的任务,无法获取锁，本次不执行");
            return actionResult(ErrorCode.NoBarcodeOutboundLockError);
        }
        FunctionResult result = new FunctionResult();
        try{
            ErrorCode errorCode = warehouseDeliveryRecordService.receive(deliveryAddVO, getUserId(), getOrgId());
            result.setCode(errorCode);
        }catch (Exception e){
            return new ActionResult(ErrorCode.Failure.getCode(), e.getMessage());
        }finally {
            lock.unlock();
        }
        return actionResult(result.getCode(), result.getValue());
    }
    
    @RequestMapping(value = "/update",method = RequestMethod.POST)
    @ApiOperation(value = "更新出库记录")
    @FastMappingInfo(needLogin = true)
    public ActionResult update(@RequestBody WarehouseDeliveryRecordVO warehouseDeliveryRecordVO)throws Exception{
        if(null == warehouseDeliveryRecordVO){
            return actionResult(ErrorCode.IllegalArument);
        }
        ErrorCode errorCode = warehouseDeliveryRecordService.update(warehouseDeliveryRecordVO);
        return actionResult(errorCode);
    }

    @RequestMapping(value = "/remove",method = RequestMethod.POST)
    @ApiOperation("出库记录删除")
    @FastMappingInfo(needLogin = true)
    public ActionResult delete(@RequestBody String[] ids){
        if(ids == null || ids.length == 0){
            return actionResult(ErrorCode.IllegalArument);
        }
        return actionResult(warehouseDeliveryRecordService.remove(Arrays.asList(ids)));
    }

    @RequestMapping(value = "/list",method = RequestMethod.POST)
    @ApiOperation("查询出库记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult listDeliveryNote(@RequestBody SearchCommonVO<WarehouseDeliveryRecordVO> condition)throws Exception{
        WarehouseDeliveryRecordVO warehouseDeliveryRecordVO =condition.getFilters();
        if(warehouseDeliveryRecordVO == null){
            warehouseDeliveryRecordVO = new WarehouseDeliveryRecordVO();
        }
        warehouseDeliveryRecordVO.setOrgId(getOrgId());
        condition.setFilters(warehouseDeliveryRecordVO);
        PageCommonVO pageCommonVO= warehouseDeliveryRecordService.list(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/export",method = RequestMethod.POST)
    @ApiOperation("导出出库记录列表")
    @FastMappingInfo(needLogin = true)
    public void export(@RequestBody String[] ids)throws Exception {
        warehouseDeliveryRecordService.export(Arrays.asList(ids));
    }

    @RequestMapping(value = "/exportAll",method = RequestMethod.POST)
    @ApiOperation("导出全部出库记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportAll(WarehouseDeliveryRecordVO condition)throws Exception {
        if(condition == null){
            condition = new WarehouseDeliveryRecordVO();
        }
        condition.setOrgId(getOrgId());
        warehouseDeliveryRecordService.exportAll(condition);
    }

    @RequestMapping(value = "/findAlreadyDeliveryNum",method = RequestMethod.POST)
    @ApiOperation("获取出库业务单已出库和未出库的数量")
    @FastMappingInfo(needLogin = true)
    public ActionResult findAlreadyDeliveryNum(String businessOrder)throws Exception{
        return actionValueResult(warehouseDeliveryRecordService.findAlreadyDeliveryNum(businessOrder, getOrgId()));
    }

    @RequestMapping(value = "/findAlreadyDeliveryList",method = RequestMethod.POST)
    @ApiOperation("获取出库业务单已出库和未出库的列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult findAlreadyDeliveryList(String businessOrder, Integer state)throws Exception{
        return actionValueResult(warehouseDeliveryRecordService.findAlreadyDeliveryList(businessOrder, state, getOrgId()));
    }

    private Integer getIndex(String msg){
        try {
            if(!msg.startsWith("index&&")){
                return 0;
            }
            String[] str = msg.split("&&");
            return new Integer(str[1]);
        }catch (Exception e){
            return 0;
        }
    }

    private String getMsg(String msg){
        try {
            if(!msg.startsWith("index&&")){
                return msg;
            }
            String[] str = msg.split("&&");
            return str[2];
        }catch (Exception e){
            return msg;
        }
    }

    private String getExceptionAllinformation(Exception ex){
        String sOut = "\r\n";
        StackTraceElement[] trace = ex.getStackTrace();
        for (StackTraceElement s : trace) {
            sOut += "\tat " + s + "\r\n";
        }
        return sOut;
    }
}
